using System;
using System.Windows.Forms;
using twistmachinev2.OPCUA;
using System.Collections.Generic;
using LogManager = twistmachinev2.CommonUse.LogManager;
using DevExpress.XtraEditors;

namespace twistmachinev2.CommonUse
{
    /// <summary>
    /// 支持OPCUA数据订阅的基础窗体类
    /// </summary>
    public partial class BaseOpcUaForm : XtraForm, IOpcUaDataSubscriber
    {
        private readonly OpcUaSubscriptionManager _subscriptionManager;
        private readonly List<string> _subscribedNodes;
        private bool _isSubscribed = false;

        /// <summary>
        /// 构造函数
        /// </summary>
        public BaseOpcUaForm()
        {
            _subscriptionManager = OpcUaSubscriptionManager.Instance;
            _subscribedNodes = new List<string>();

            // 窗体加载时自动订阅
            this.Load += BaseOpcUaForm_Load;
            this.FormClosed += BaseOpcUaForm_FormClosed;
        }

        /// <summary>
        /// 窗体加载事件
        /// </summary>
        private void BaseOpcUaForm_Load(object sender, EventArgs e)
        {
            if (!_isSubscribed)
            {
                SubscribeToOpcUaData();
                _isSubscribed = true;
            }
        }

        /// <summary>
        /// 窗体关闭事件
        /// </summary>
        private void BaseOpcUaForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            UnsubscribeFromOpcUaData();
        }

        /// <summary>
        /// 订阅OPCUA数据 - 子类可以重写此方法来订阅特定节点
        /// </summary>
        protected virtual void SubscribeToOpcUaData()
        {
            // 默认订阅所有数据变化
            _subscriptionManager.Subscribe(this);
        }

        /// <summary>
        /// 取消订阅OPCUA数据
        /// </summary>
        protected virtual void UnsubscribeFromOpcUaData()
        {
            _subscriptionManager.Unsubscribe(this);

            // 取消订阅所有特定节点
            foreach (var nodeId in _subscribedNodes)
            {
                _subscriptionManager.Unsubscribe(nodeId, this);
            }
            _subscribedNodes.Clear();
        }

        /// <summary>
        /// 订阅特定节点
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        protected void SubscribeToNode(string nodeId)
        {
            if (!string.IsNullOrEmpty(nodeId) && !_subscribedNodes.Contains(nodeId))
            {
                _subscriptionManager.Subscribe(nodeId, this);
                _subscribedNodes.Add(nodeId);
            }
        }

        /// <summary>
        /// 取消订阅特定节点
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        protected void UnsubscribeFromNode(string nodeId)
        {
            if (!string.IsNullOrEmpty(nodeId) && _subscribedNodes.Contains(nodeId))
            {
                _subscriptionManager.Unsubscribe(nodeId, this);
                _subscribedNodes.Remove(nodeId);
            }
        }

        /// <summary>
        /// 获取OPCUA服务管理器
        /// </summary>
        protected OpcUaServiceManager OpcUaService => OpcUaServiceManager.Instance;

        /// <summary>
        /// 获取数据模型
        /// </summary>
        /// <param name="objectName">对象名称</param>
        /// <returns>数据模型</returns>
        protected DynamicDataModel GetDataModel(string objectName = "TwistMachine")
        {
            return OpcUaService.GetDataModel(objectName);
        }

        /// <summary>
        /// 安全地在UI线程上执行操作
        /// </summary>
        /// <param name="action">要执行的操作</param>
        protected void SafeInvoke(Action action)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(action);
            }
            else
            {
                action();
            }
        }

        /// <summary>
        /// 数据变化事件处理 - 子类应该重写此方法
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <param name="value">新值</param>
        public virtual void OnDataChanged(string nodeId, object value)
        {
            // 记录数据变化
            // OPC UA数据变化

            // 默认实现：在UI线程上调用虚方法
            SafeInvoke(() => OnDataChangedOnUIThread(nodeId, value));
        }

        /// <summary>
        /// 在UI线程上处理数据变化 - 子类可以重写此方法
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <param name="value">新值</param>
        protected virtual void OnDataChangedOnUIThread(string nodeId, object value)
        {
            // 子类可以重写此方法来处理具体的数据变化
        }

        /// <summary>
        /// 连接状态变化事件处理 - 子类应该重写此方法
        /// </summary>
        /// <param name="isConnected">是否已连接</param>
        public virtual void OnConnectionStatusChanged(bool isConnected)
        {
            // 记录连接状态变化
            // LogManager.LogOpcUaConnectionStatus(OpcUaService?.ServerUrl ?? "Unknown", isConnected ? "已连接" : "未连接");

            // 默认实现：在UI线程上调用虚方法
            SafeInvoke(() => OnConnectionStatusChangedOnUIThread(isConnected));
        }

        /// <summary>
        /// 在UI线程上处理连接状态变化 - 子类可以重写此方法
        /// </summary>
        /// <param name="isConnected">是否已连接</param>
        protected virtual void OnConnectionStatusChangedOnUIThread(bool isConnected)
        {
            // 子类可以重写此方法来处理连接状态变化
            // 例如：更新状态栏、启用/禁用控件等
        }

        /// <summary>
        /// 读取节点数据
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <returns>读取结果</returns>
        protected async System.Threading.Tasks.Task<OperateResult<object>> ReadNodeAsync(string nodeId)
        {
            // 开始读取OPC UA节点数据
            var result = await OpcUaService.ReadNodeAsync(nodeId);

            if (result.IsSuccess)
            {
                // OPC UA节点数据读取成功
            }
            else
            {
                // OPC UA节点数据读取失败
            }

            return result;
        }

        /// <summary>
        /// 写入节点数据
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <param name="value">要写入的值</param>
        /// <returns>写入结果</returns>
        protected async System.Threading.Tasks.Task<OperateResult> WriteNodeAsync(string nodeId, object value)
        {
            // 开始写入OPC UA节点数据
            var result = await OpcUaService.WriteNodeAsync(nodeId, value);

            if (result.IsSuccess)
            {
                LogManager.LogOpcUaDataChange(nodeId, "未知", value, "用户操作");
                // OPC UA节点数据写入成功
            }
            else
            {
                // OPC UA节点数据写入失败
            }

            return result;
        }

        /// <summary>
        /// 显示操作结果消息
        /// </summary>
        /// <param name="result">操作结果</param>
        /// <param name="successMessage">成功时显示的消息</param>
        protected void ShowOperateResult(OperateResult result, string successMessage = "操作成功")
        {
            if (result.IsSuccess)
            {
                // 操作成功
                MessageBox.Show(successMessage, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                LogManager.LogError($"操作失败: {result.Message}");
                MessageBox.Show($"操作失败：{result.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 显示操作结果消息（泛型版本）
        /// </summary>
        /// <typeparam name="T">结果类型</typeparam>
        /// <param name="result">操作结果</param>
        /// <param name="successMessage">成功时显示的消息</param>
        protected void ShowOperateResult<T>(OperateResult<T> result, string successMessage = "操作成功")
        {
            if (result.IsSuccess)
            {
                // 操作成功
                MessageBox.Show(successMessage, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                LogManager.LogError($"操作失败: {result.Message}");
                MessageBox.Show($"操作失败：{result.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // BaseOpcUaForm
            // 
            this.ClientSize = new System.Drawing.Size(1034, 727);
            this.Name = "BaseOpcUaForm";
            this.ResumeLayout(false);

        }
    }
}